<!DOCTYPE html>
<title>Binary Data Polyfill Demo</title>
<meta charset="UTF-8">

<script src="../bindata.js"></script>
<body>
<style>
div { font-family: monospace; white-space: pre; }
div.pass { color: #00c000; font-weight: bold; }
div.fail { color: #c00000; font-weight: bold; }
body.fail { background-color: #ffc0c0; }
</style>
<script>
function log(t, className) {
  var e = document.createElement("div");
  e.appendChild(document.createTextNode(t));
  if (className) {
    e.className = className;
  }
  document.body.appendChild(e);
  if (className === 'fail') {
    document.body.classList.add('fail');
  }
}

function separate() {
  var e = document.createElement("hr");
  document.body.appendChild(e);
}
function stringify(value) {
  if (typeof value === 'undefined') return "undefined";
  if (typeof value === 'function') return "[function " + value.name + "]";
  var json = JSON.stringify(value);
  return json ? json : Object.prototype.toString.call(value);
}
function evalAndShow(_expr) {
  try {
    var res = eval(_expr);
    var json = JSON.stringify(res);
    log(_expr + " == " + stringify(res));
  } catch (ex) {
    log(_expr + " threw: " + ex, "fail");
  }
}
function evalAndLog(_expr) {
  try {
    var res = eval(_expr);
    log(_expr);
  } catch (ex) {
    log(_expr + " threw: " + ex, "fail");
  }
}
function expect(_expr, _expected) {
  if (arguments.length < 2) _expected = true;
  try {
    var res = eval(_expr);
    if (res === _expected) {
      var json = JSON.stringify(res);
      log(_expr + " === " + stringify(res), "pass");
    } else {
      log(_expr + " === " + stringify(res) + " - expected: " + stringify(_expected), "fail");
    }
  } catch (ex) {
    log(_expr + " threw: " + ex, "fail");
  }
}

evalAndLog("Point2D = new StructType({ x: uint32, y: uint32 });");
evalAndLog("Color = new StructType({ r: uint8, g: uint8, b: uint8 });");
evalAndLog("Pixel = new StructType({ point: Point2D, color: Color });");
log("\n");
evalAndLog("Triangle = new ArrayType(Pixel, 3);");
evalAndLog("t = new Triangle([{ point: { x:  0, y: 0 }, color: { r: 255, g: 255, b: 255 } }," + "\n" +
           "                  { point: { x:  5, y: 5 }, color: { r: 128, g: 0,   b: 0   } }," + "\n" +
           "                  { point: { x: 10, y: 0 }, color: { r: 0,   g: 0,   b: 128 } }]);");
expect("t[0].point.x", 0);
expect("t[0].point.y", 0);
expect("t[0].color.r", 255);
expect("t[0].color.g", 255);
expect("t[0].color.b", 255);
expect("t[1].point.x", 5);
expect("t[1].point.y", 5);
expect("t[1].color.r", 128);
expect("t[1].color.g", 0);
expect("t[1].color.b", 0);
expect("t[2].point.x", 10);
expect("t[2].point.y", 0);
expect("t[2].color.r", 0);
expect("t[2].color.g", 0);
expect("t[2].color.b", 128);
expect("t.buffer instanceof ArrayBuffer");
expect("t.byteOffset", 0);
expect("t.byteLength", 33);
evalAndLog("c = new Color({r: 1, g: 2, b: 3})");
expect("c.r", 1);
evalAndLog("c.update({r: 11, g: 22, b: 33})");
expect("c.r", 11);

expect("c instanceof Color");
expect("c instanceof Data");
expect("Color instanceof Type");

expect("t instanceof Triangle");
expect("t instanceof Data");
expect("Triangle instanceof Type");

separate(); // ----------------------------------------------------------

evalAndLog("t = uint16");
expect("Object.prototype.toString.call(t)", "[object DataType]");
expect("t.__proto__", Function.prototype);
expect("t.__DataType__", "uint16");
evalAndShow("t.__Convert__");
evalAndShow("t.__IsSame__");
evalAndShow("t.__Cast__");
evalAndShow("t.__CCast__");
evalAndShow("t.__Reify__");
expect("t.bytes", 2);

log("\n");

evalAndLog("n = t(123.456)");
expect("typeof n", "number");
expect("n", 123);

separate(); // ----------------------------------------------------------

evalAndLog("t = new ArrayType(uint16, 4)");
expect("Object.prototype.toString.call(t)", "[object DataType]");
evalAndShow("t.__proto__");
expect("t.__DataType__", "ArrayType");
evalAndShow("t.__ElementType__");
expect("t.__Length__", 4);
evalAndShow("t.__Convert__");
evalAndShow("t.__IsSame__");
evalAndShow("t.__Construct__");
evalAndShow("t.__Reify__");
evalAndShow("t.prototype");
evalAndShow("t.prototype.__proto__");
evalAndShow("t.prototype.constructor");
evalAndShow("t.prototype.fill");
evalAndShow("t.elementType");
evalAndShow("t.length");
expect("t.bytes", 8);

log("\n");

evalAndLog("a = new t([1, 2, 300, 0])");
evalAndShow("a.__Class__")
evalAndShow("a.__proto__")
evalAndShow("a.__Value__")
evalAndShow("a.__DataType__")
expect("a.length", 4)
expect("a[0]", 1);
expect("a[1]", 2);
expect("a[2]", 300);
expect("a[3]", 0);
expect("a.buffer instanceof ArrayBuffer");
expect("a.byteOffset", 0);
expect("a.byteLength", 8);

separate(); // ----------------------------------------------------------

evalAndLog("t = new StructType({a: uint8, b: uint8})");
expect("Object.prototype.toString.call(t)", "[object DataType]");
evalAndShow("t.__proto__");
expect("t.__DataType__", "StructType");
evalAndShow("t.__Convert__");
evalAndShow("t.__IsSame__");
evalAndShow("t.__Construct__");
evalAndShow("t.__Reify__");
evalAndShow("t.prototype.constructor");
evalAndShow("t.fields");
expect("t.bytes", 2);

log("\n");

evalAndLog("s = new t({a: 2.5, b: 247})");
evalAndShow("s.__Class__");
evalAndShow("s.__proto__");
evalAndShow("s.__Value__");
evalAndShow("s.__DataType__");
evalAndShow("s.constructor");
expect("s['a']", 2);
expect("s['b']", 247);
expect("s.buffer instanceof ArrayBuffer");
expect("s.byteOffset", 0);
expect("s.byteLength", 2);

separate(); // ----------------------------------------------------------

S = new StructType({v: uint8});
A = new ArrayType(S);
a = new A(16);
for (i = 0; i < 16; ++i) { a[i] = { v: i * 4 }; }
p = new StructView(S);


</script>
</body>
